﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Newtonsoft.Json.Linq;
using Lin.Invoke;
using System.Reflection;
using Yahoo.Yui.Compressor;

namespace Lin.JSDocument
{
    /*
     * @name 方法名称
     * @link 链接页面
     * @param 参数描述
    */
    public partial class FrmMain : Form
    {
        string openPath = Application.StartupPath;
        string outPath = Application.StartupPath;
        JObject json = null;

        public FrmMain()
        {
            InitializeComponent();
            //Win32.AllocConsole();
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            this.txtOpen.Text = openPath;
            this.txtOut.Text = outPath;

            this.folderDialog.SelectedPath = openPath;

            GetJsFile();
        }

        private void GetJsFile() {
            var file = Directory.GetFiles(openPath, "*.js");
            var name = string.Empty;

            this.txtJslist.Items.Clear();

            foreach (var js in file)
            {
                name = js.Substring(js.LastIndexOf(@"\") + 1);

                if (name.IndexOf("-min") != -1)
                {
                    continue;
                }

                this.txtJslist.Items.Add(name);
            }
        }

        private void CreateJson(string file, string[] line)
        {
            var star = false;
            var over = false;
            var keys = string.Empty;

            JArray exps = null;
            JArray param = null;
            JObject info = new JObject();
            JObject desc = new JObject();
            JObject back = null;

            foreach (var ln in line)
            {
                if (ln.IndexOf("/**!") != -1)
                {
                    star = true;
                    over = false;
                    exps = new JArray();
                    desc = new JObject();
                    continue;
                }
                if (ln.IndexOf("!*/") != -1)
                {
                    star = false;
                    over = true;
                    continue;
                }

                if (star && ln.IndexOf("@") == -1)
                {
                    exps.Add(ln.Trim().Replace("/*", "").Replace(" ", "&nbsp;"));
                }
                else if (star)
                {
                    if (ln.IndexOf("@name") != -1)
                    {
                        desc.Add("name", ln.Replace("/*", "").Replace("@name", "").Replace(" ", ""));
                    }
                    else if (ln.IndexOf("@param") != -1)
                    {
                        var lne = ln.Replace("/*", "").Replace("@param", "").Replace(" ", "");
                        var par = new JObject();

                        if (lne.IndexOf("{") != -1)
                        {
                            par.Add("type", lne.Substring(lne.IndexOf("{"), lne.IndexOf("}") + 1));
                        }

                        if (lne.IndexOf("&") != -1)
                        {
                            if (lne.IndexOf("#") == -1)
                            {
                                par.Add("name", lne.Substring(lne.IndexOf("&") + 1));
                            }
                            else
                            {
                                par.Add("name", lne.Substring(lne.IndexOf("&") + 1, lne.IndexOf("#") - lne.IndexOf("&") - 1));
                            }
                        }

                        if (lne.IndexOf("#") != -1)
                        {
                            par.Add("text", lne.Substring(lne.IndexOf("#") + 1));
                        }


                        if (param == null)
                        {
                            param = new JArray();
                        }

                        param.Add(par);
                    }
                    else if (ln.IndexOf("@return") != -1)
                    {

                        back = new JObject();

                        var lne = ln.Replace("/*", "").Replace("@return", "").Replace(" ", "");
                        if (lne.IndexOf("{") != -1)
                        {
                            back.Add("type", lne.Substring(lne.IndexOf("{"), lne.IndexOf("}") + 1));
                        }

                        if (lne.IndexOf("#") != -1)
                        {
                            back.Add("text", lne.Substring(lne.IndexOf("#") + 1));
                        }
                    }
                }

                if (over)
                {
                    keys = ln.Replace(" ", "").Replace("function", "").Replace("=", "").Replace("{", "").Replace("var", "");
                    desc.Add("desc", exps);
                    desc.Add("param", param);
                    desc.Add("return", back);
                    info.Add(keys, desc);

                    over = false;
                    param = null;
                    back = null;
                    continue;
                }
            }

            json.Add(file, info);
        }

        private void CreateHtml()
        {
            if (!Directory.Exists(outPath + "/JsDoc"))
            {
                Directory.CreateDirectory(outPath + "/JsDoc");
            }

            var html = Properties.Resources.temple.Replace("{0}", json.ToString());

            try
            {
                File.WriteAllText(outPath + "/JsDoc/index.html", html.ToString(), Encoding.UTF8);

                MessageBox.Show("生成成功.");
            }
            catch (Exception e)
            {
                MessageBox.Show("生成失败." + e.Message);
            }
        }

        public class Win32
        {
            [DllImport("kernel32.dll")]
            public static extern Boolean AllocConsole();
            [DllImport("kernel32.dll")]
            public static extern Boolean FreeConsole();
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (this.folderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                openPath = this.txtOpen.Text = this.folderDialog.SelectedPath;

                GetJsFile();
            }
        }

        private void btnOut_Click(object sender, EventArgs e)
        {
            if (this.folderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                outPath = this.txtOut.Text = this.folderDialog.SelectedPath;
            }
        }

        private void btnCreateHtml_Click(object sender, EventArgs e)
        {
            if (txtOpen.Text == string.Empty)
            {
                MessageBox.Show("Js目录不能为空.");
                return;
            }
            if (txtOut.Text == string.Empty)
            {
                MessageBox.Show("输出目录不能为空.");
                return;
            }

            var file = Directory.GetFiles(openPath, "*.js");

            if (file.Count() == 0)
            {
                MessageBox.Show("没有需要生成的Javascript文件.");
                return;
            }

            json = new JObject();

            foreach (var f in file)
            {
                var info = new FileInfo(f);

                CreateJson(info.Name, File.ReadAllLines(f));
            }

            CreateHtml();
        }

        private void btnCreateJsmin_Click(object sender, EventArgs e)
        {

            this.btnCreateJsmin.Text = "Js压缩中...";
            this.Enabled = false;

            JavaScriptCompressor jsc = new JavaScriptCompressor();

            var i = 0;
            var filename = string.Empty;
            for(;i<this.txtJslist.Items.Count;i++)
            {
                filename = this.txtJslist.Items[i].ToString();
                try
                {
                    var file = File.ReadAllText(openPath + @"\"+filename.ToString());
                    jsc.Encoding = Encoding.UTF8;
                    var context = jsc.Compress(file);
                    File.WriteAllText(outPath + @"\"+filename.ToString().Replace(".js","-min.js"), context, Encoding.UTF8);

                    txtJslist.Items[i] = filename + " (加密完成)";
                }
                catch (Exception ex)
                {
                    txtJslist.Items[i] = filename + " (加密失败)";
                }
            }

            this.btnCreateJsmin.Text = "Jscript加密";
            this.Enabled = true;
        }
    }
}
